package com.yunchao.library.socket.logger

import com.yunchao.library.socket.config.Message
import com.yunchao.library.socket.config.MessageContent
import com.yunchao.library.socket.config.MessageHeader
import com.yunchao.library.socket.enum.ConnectionEvent
import com.yunchao.library.socket.extensions.hexString
import timber.log.Timber
import java.text.SimpleDateFormat
import java.util.Locale

/**
 * 通用的Socket日志打印工具
 */
object SocketLogger {
    private const val TAG = "SocketTracing"

    // 使用更高效的日期格式化方式
    private val dateFormat by lazy {
        ThreadLocal.withInitial {
            SimpleDateFormat("HH:mm:ss.SSS", Locale.getDefault())
        }.get()
    }

    /**
     * 最简化的日志方法，所有信息从Message对象中获取
     * @param message 消息对象
     */
    fun logMessage(direction: String, message: Message) {
        val timestamp = dateFormat?.format(System.currentTimeMillis())
        val threadName = Thread.currentThread().name

        Timber.tag(TAG).d(
            """
              [$timestamp][$threadName] $direction message:
                    Header: ${message.header} 
                    Transport: ${message.header.transport.code.toString(16)}
                    Payload: ${
                when (val content = message.content) {
                    is MessageContent.ChunkedMessage -> {
                        ("CHUNKED(${content.chunks.size}/${content.totalSize}) ")
                    }

                    is MessageContent.SingleMessage -> {
                        ("hex=${content.data.hexString} ")
                    }
                }
            }
            """.trimIndent()
        )

    }

    /**
     * 最简化的日志方法，所有信息从Message对象中获取
     * @param header 消息对象
     */
    fun logMessage(
        direction: String,
        header: MessageHeader,
        bodyBytes: ByteArray,
    ) {
        val timestamp = dateFormat?.format(System.currentTimeMillis())
        val threadName = Thread.currentThread().name

        Timber.tag(TAG).v(
            """
              [$timestamp][$threadName] $direction message:
                   Header: $header 
                   Transport: ${header.transport.code.toString(16)}
                   Payload: ${bodyBytes.hexString}
            """.trimIndent()
        )
    }

    // 特殊情况的日志方法（如连接状态、错误等）
    fun logConnectionState(event: ConnectionEvent) {
        val timestamp = dateFormat?.format(System.currentTimeMillis())
        val threadName = Thread.currentThread().name

        val message = when (event) {
            is ConnectionEvent.Connecting -> "正在连接服务器..."
            is ConnectionEvent.Connected -> "成功连接到 ${event.host}:${event.port}"
            is ConnectionEvent.Disconnected -> "与服务器断开连接"
            is ConnectionEvent.Reconnecting -> "正在尝试第${event.attempt}次重新连接，延迟${event.delayMs}毫秒"
            is ConnectionEvent.Error -> "连接发生错误 ${event.cause.message}"
        }

        Timber.tag(TAG).i("[$timestamp][$threadName] CONNECTION: $message")
    }

    fun logOperation(operation: String, details: String? = null) {

        val timestamp = dateFormat?.format(System.currentTimeMillis())
        val threadName = Thread.currentThread().name

        val message = buildString {
            append("[$timestamp][$threadName] OP: $operation")
            details?.let { append(" - $it") }
        }

        Timber.tag(TAG).d(message)
    }

    fun logError(errorMsg: String, exception: Throwable? = null) {
        val timestamp = dateFormat?.format(System.currentTimeMillis())
        val threadName = Thread.currentThread().name
        val message = "[$timestamp][$threadName] ERROR: $errorMsg"

        if (exception != null) {
            Timber.tag(TAG).e(exception, message)
        } else {
            Timber.tag(TAG).e(message)
        }
    }

    // 新增警告日志方法
    fun logWarning(warningMsg: String, exception: Throwable? = null) {

        val timestamp = dateFormat?.format(System.currentTimeMillis())
        val threadName = Thread.currentThread().name
        val message = "[$timestamp][$threadName] WARN: $warningMsg"

        if (exception != null) {
            Timber.tag(TAG).w(exception, message)
        } else {
            Timber.tag(TAG).w(message)
        }
    }
}
